import logging
import os
import asyncio
import inspect
from collections import OrderedDict
from typing import Optional
from logging.handlers import RotatingFileHandler
import uuid

class AsyncTaskLogger:
    _loggers = OrderedDict()  # 存储已创建的logger
    _log_dir = "logs"  # 日志目录

    def __init__(self):
        if not os.path.exists(self._log_dir):
            os.makedirs(self._log_dir)


    @classmethod
    def _get_caller_function_name(cls) -> str:
        """获取调用日志的函数的名称"""
        # 获取调用栈，跳过当前函数（_log）和logger方法
        stack = inspect.stack()
        for frame_info in stack[2:]:  # 跳过前两层（当前函数和logger调用）
            func_name = frame_info.function
            if not func_name.startswith("_"):  # 忽略内部方法
                return func_name
        return "unknown_function"

    @classmethod
    def cleanup_logger(cls, task_id: Optional[str] = None):
        """清理指定任务的logger资源"""
        if task_id in cls._loggers:
            logger = cls._loggers[task_id]
            # 关闭所有handlers
            for handler in logger.handlers[:]:
                logger.removeHandler(handler)
                if hasattr(handler, 'close'):
                    handler.close()
            # 从字典中移除
            del cls._loggers[task_id]

    @classmethod
    def cleanup_all_loggers(cls):
        """清理所有logger资源"""
        for task_id in list(cls._loggers.keys()):
            cls.cleanup_logger(task_id)

    @classmethod
    def cleanup_old_loggers(cls, max_loggers=100):
        """清理旧的logger，保持_loggers字典大小在合理范围内"""
        if len(cls._loggers) > max_loggers:
            # 按创建时间排序，删除最旧的logger
            logger_items = list(cls._loggers.items())
            # 这里假设logger的创建时间可以通过某种方式获取
            # 简单起见，我们删除一半的logger
            to_remove = logger_items[:len(logger_items) // 2]
            for task_id, _ in to_remove:
                cls.cleanup_logger(task_id)
            # print(f"已清理 {len(to_remove)} 个旧logger，当前剩余 {len(cls._loggers)} 个")

    @classmethod
    def get_logger(cls, task_id: Optional[str] = None) -> logging.Logger:
        """获取或创建任务专用的日志记录器"""

        # 定期清理旧logger（如果使用缓存的话）
        cls.cleanup_old_loggers()

        if task_id in cls._loggers:
            return cls._loggers[task_id]

        logger = logging.getLogger(f"async_task_{task_id}")
        logger.setLevel(logging.DEBUG)

        # 如果logger已经有handlers，直接返回
        if logger.handlers:
            cls._loggers[task_id] = logger
            return logger

        # 创建新的文件处理器
        log_file = os.path.join(cls._log_dir, f"task_{task_id}.log")
        file_handler = RotatingFileHandler(
            log_file, maxBytes=10 * 1024 * 1024, backupCount=5, encoding="utf-8"
        )
        file_handler.setLevel(logging.DEBUG)

        # 改进日志格式：时间 - 任务ID - 函数名 - 日志级别 - 消息
        formatter = logging.Formatter(
            "%(asctime)s - %(levelname)s - [%(funcName)s] - %(message)s"
        )
        file_handler.setFormatter(formatter)

        logger.addHandler(file_handler)
        
        # 可选：仍然缓存logger用于资源管理
        cls._loggers[task_id] = logger

        return logger

    @classmethod
    def log(cls, level: int, message: str, task_id: Optional[str] = None):
        """通用日志方法，自动记录函数名"""
        logger = cls.get_logger(task_id)
        func_name = cls._get_caller_function_name()
        logger.log(level, f"[{func_name}] {message}")

    @classmethod
    def log_task_start(cls, task_id: Optional[str] = None, **kwargs):
        """记录任务开始"""
        logger = cls.get_logger(task_id)
        func_name = cls._get_caller_function_name()
        logger.info(f"[{func_name}] 🚀 Task started. Task ID: {task_id}")
        if kwargs:
            logger.debug(f"[{func_name}] 📝 Task parameters: {kwargs}")

    @classmethod
    def log_task_end(cls, task_id: Optional[str] = None, result=None):
        """记录任务结束"""
        logger = cls.get_logger(task_id)
        func_name = cls._get_caller_function_name()
        if result is not None:
            logger.info(f"[{func_name}] ✅ Task '{task_id}' completed. Result: {result}")
        else:
            logger.info(f"[{func_name}] ✅ Task '{task_id}' completed.")

    @classmethod
    def log_exception(cls, exception: Exception, task_id: Optional[str] = None, message: Optional[str] = None):
        """记录异常"""
        logger = cls.get_logger(task_id)
        func_name = cls._get_caller_function_name()
        if message is not None:
            logger.error(f"[{func_name}] ❌ Task '{task_id}' failed: {str(exception)} {message}", exc_info=True)
        else:
            logger.error(f"[{func_name}] ❌ Task '{task_id}' failed: {str(exception)}", exc_info=True)